package com.example.active_record.domain;

import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student extends Model<Student> {
    @TableId(value = "sid")
    private Integer id;
    @TableField("sname")
    private String name;
    private String email;
    private String gender;
    private Integer age;
    //测试  乐观锁插件  OptimisticLockerInnerInterceptor
    @Version
    private Integer version;
    @TableLogic
    @TableField(fill = FieldFill.INSERT)   //自动填充
    private Integer deleted;

    /*填充策略：

值	                描述
FieldFill.DEFAULT	            默认不处理
FieldFill.INSERT	            插入操作填充字段
FieldFill.UPDATE	            更新操作填充字段
FieldFill.INSERT_UPDATE	    插入操作和更新操作均填充字段

1，为实体类的自动填充字段添加@TableField
2，自定义填充类实现MetaObjectHandler接口
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

   * 插入时填充逻辑
   * @param metaObject 元对象
   *
    @Override
    public void insertFill(MetaObject metaObject) {

         * 参数1：填充字段名
         * 参数2：参数值
         * 参数3：元对象

        this.setFieldValByName("deleted", 0, metaObject);
    }


     * 更新时填充逻辑
     * @param metaObject

    @Override
    public void updateFill(MetaObject metaObject) {
    }
}*/
}
/*Active Record(活动记录)，是一种领域模型模式，
特点是一个模型类对应关系型数据库中的一个表，
而模型类的一个实例对应表中的一行记录。
在MyBatisPlus中，AR模式即在实体类中封装了对数据库的访问，
而不通过mapper类。*/

/*虽然操作数据库不通过mapper类，但需要编写mapper类并继承BaseMapper

public interface StudentMapper extends BaseMapper<Student> {
}

实体类继承Model类，开启AR模式

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student extends Model<Student> {}*/



/*
乐观锁在数据进行提交更新的时候，才会正式对数据的冲突
与否进行检测，如果冲突，则返回给用户异常信息，让用户决定如何去做
使用MyBatisPlus乐观锁插件：

1注册乐观锁插件

// 注册插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
  MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
  // 分页插件
  interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
  // 防止全表更新与删除插件
  interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
  // 乐观锁插件
  interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
  return interceptor;
}
2修改实体类，添加version列并在该属性上面增加@Version

@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("tb_student")
public class Student extends Model<Student> {
  @TableId(value = "sid",type = IdType.AUTO)
  private Integer id;
  @TableField("sname")
  private String name;
  private String email;
  private String gender;
  private Integer age;
  @Version
  private Integer version;
}
3修改数据库表，添加一列整型version字段并设置默认值为0

4测试修改功能

// 修改
@Test
public void testUpdate1() {
  Student student = new Student();
  student.setId(10);
  student.setName("百战程序员2");
  //如果版本号和数据库一致更新成功，版本号+1,如果不一致更新失败
  student.setVersion(10);
  student.updateById();
}*/

/*MyBatisPlus逻辑删除_概念
* 在实际开发中，由于数据十分重要，为了避免误删除数据导致数据无法
* 找回，我们往往不会使用物理删除，即从数据库中直接删除数据。
* 而是采用逻辑删除的方式，即不会真正在数据库删除数据，
* 而是通过一个变量代表它被删除。
*
* deleted属性代表该数据是否删除，0代表未删除，1代表已删除。
* 此时增删改查的Sql语句发生变化：

插入: 不作限制
查找: 追加where条件过滤掉已删除数据。
更新: 追加where条件防止更新到已删除数据。
删除: 转变为更新
例如:

删除: update user set deleted=1 where id = 1 and deleted=0
查找: select id,name,deleted from user where deleted=0
*
*
* 在配置文件配置逻辑删除

# mybatis-plus相关配置
mybatis-plus:
 # 全局配置
  global-config:
   db-config:
   # 全局逻辑删除的字段名
    logic-delete-field: deleted
   # 逻辑已删除值(默认为 1)
    logic-delete-value: 1
   # 逻辑未删除值(默认为 0)
    logic-not-delete-value: 0


修改实体类，添加逻辑删除属性

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student extends Model<Student> {
  @TableId(value = "sid")
  private Integer id;
  @TableField("sname")
  private String name;
  private String email;
  private String gender;
  private Integer age;
  @Version
  private Integer version;
  @TableLogic  //逻辑删除属性
  private Integer deleted;
}
修改数据库表，添加一列整型deleted字段并设置默认值为0

测试删除和查询方法，会看到删除时将deleted字段变为1，查询时添加条件deleted=0*/